package com.billy.ohos.swipe.internal;

import com.billy.ohos.swipe.SmartSwipe;

import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.Shader;
import ohos.agp.utils.Color;
import ohos.agp.utils.Rect;
import ohos.app.Context;

import ohos.multimodalinput.event.TouchEvent;

import static com.billy.ohos.swipe.SwipeConsumer.*;

/**
 * @author billy.qi
 */
public class ScrimView extends Component implements Component.LayoutRefreshedListener, Component.DrawTask, Component.TouchEventListener {
    public static final float MAX_PROGRESS = 1F;
    public static final float MIN_PROGRESS = 0F;
    private int mSize = 60;
    private final Paint mPaint;
    private Rect mBounds = new Rect();
    private int mScrimColor;
    private int mBaseAlpha;
    private int mDirection;
    private Paint mShadowPaint;
    private Rect mShadowRect = new Rect();
    private int mShadowColor = 0x80000000;
    private int mShadowDirection;

    public ScrimView(Context context) {
        super(context);
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.FILL_STYLE);
        mShadowPaint = new Paint();
        mShadowPaint.setDither(true);
        mShadowPaint.setAntiAlias(true);
        addDrawTask(this);
        setLayoutRefreshedListener(this);
    }


    @Override
    public void onRefreshed(Component component) {
        this.mBounds.right = component.getWidth();
        this.mBounds.bottom = component.getHeight();
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        if (mScrimColor != 0) {
            canvas.drawRect(mBounds, mPaint);
        }
        if (mSize > 0 && mShadowColor != 0 && (mDirection & DIRECTION_ALL) > 0) {
            canvas.save();
            switch (mShadowDirection) {
                default:
                    break;
                case DIRECTION_RIGHT:
                    canvas.translate(mBounds.right - mSize, 0);
                    break;
                case DIRECTION_BOTTOM:
                    canvas.translate(0, mBounds.bottom - mSize);
                    break;
            }
            canvas.clipRect(mShadowRect);
//            canvas.drawPaint(mShadowPaint);
            canvas.restore();
        }
    }

    public void setProgress(float progress) {
        float mProgress = SmartSwipe.ensureBetween(progress, MIN_PROGRESS, MAX_PROGRESS);
        final int alpha = (int) (mBaseAlpha * mProgress);
        final int color = alpha << 24 | (mScrimColor & 0xFFFFFF);
        mPaint.setColor(new Color(color));
        // invalidate();
    }

    public void setScrimColor(int scrimColor) {
        this.mScrimColor = scrimColor;
        mBaseAlpha = (mScrimColor & 0xFF000000) >>> 24;
        invalidate();
    }

    public void setDirection(int direction, int shadowColor, int shadowDirection, int shadowSize, int parentWidth, int parentHeight) {
        this.mDirection = direction;
        this.mShadowColor = shadowColor;
        this.mShadowDirection = shadowDirection;
        this.mSize = shadowSize;
        if (mShadowColor == 0) {
            return;
        }
        int left = 0, top = 0, right, bottom;
        switch (mShadowDirection) {
            default:
                return;
            case DIRECTION_LEFT:
            case DIRECTION_RIGHT:
                right = mSize;
//                top = parentHeight;
                bottom = parentHeight;
                break;
            case DIRECTION_TOP:
            case DIRECTION_BOTTOM:
                right = parentWidth;
                bottom = mSize;
                break;
        }
        mShadowRect.right = right;
        mShadowRect.bottom = bottom;
        int alpha = (mShadowColor & 0xFF000000) >>> 24;
        int steps = 30;
        float[] positions = new float[steps + 1];
        Color[] colors = new Color[steps + 1];
        boolean revert = mShadowDirection == DIRECTION_LEFT || mShadowDirection == DIRECTION_TOP;
        for (int i = 0; i <= steps; i++) {
            positions[i] = i * 1F / steps;
        }
        float position;
        for (int i = 0; i <= steps; i++) {
            position = positions[revert ? steps - i : i];
            int color = ((int) (alpha * position * position) << 24) | (mShadowColor & 0xFFFFFF);
            colors[i] = new Color(color);
        }

        boolean horizontal = direction == DIRECTION_LEFT || direction == DIRECTION_RIGHT;
//        if (horizontal) {
//            top = bottom = bottom >> 1;
//        } else {
//            left = right = right >> 1;
//        }
        //todo 线性渐变没有对应，只能这么写了，看效果如何
        LinearGradient shader = new LinearGradient(colors, LinearGradient.TileMode.CLAMP_TILEMODE);
        mShadowPaint.setShader(shader, Paint.ShaderType.LINEAR_SHADER);
//        mShadowPaint.setShader(shader);
        invalidate();
    }

    public int getShadowColor() {
        return mShadowColor;
    }

    @Override
    public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
        return false;
    }

    private static class LinearGradient extends Shader {
        public LinearGradient(Color[] colors, TileMode newTileMode) {
            super(colors, newTileMode);
        }
    }
}
